ποΈGitΠ―ΡΠ°ποΈ
feature/docs/README.md 2d20cd8a4708e2ef66e98d5259f3a97ec93f240a (2d20cd8a) Text, 6.49 KB
T383838:feature:docs
Overview
The T383838:feature:docs module is an in-app documentation browser with Compose Multiplatform UI. It bundles the Meshtastic user guide and developer guide as Compose resources at build time, provides full-text keyword search, Crowdin-backed multilingual content, optional ML Kit runtime translation (Google Play flavor), and a "Chirpy" AI Q&A assistant (Gemini Nano on Google Play; keyword fallback on F-Droid / Desktop / iOS).
Targets: Android Β· JVM (Desktop) Β· iOS (via T383838meshtastic.kmp.feature convention plugin)
Key Responsibilities
β’ Bundle T383838docs/en/user/**/*.md and T383838docs/en/developer/**/*.md as Compose resources at build time
β’ Sync Crowdin-translated locales into T383838composeResources/files/{locale}/docs/
β’ Keyword search (TF-IDF style) across the full doc bundle
β’ Locale-aware content loading with Crowdin β ML Kit fallback chain
β’ Adaptive list/detail layout (single pane on phones, split pane on tablets/desktop)
β’ Chirpy AI assistant: streaming Q&A against in-app docs via Gemini Nano or keyword fallback
Source Structure
T282828
src/commonMain/kotlin/org/meshtastic/feature/docs/
βββ ai/
β βββ AIDocAssistant.kt β interface (Gemini Nano / keyword fallback)
β βββ ChirpySessionHolder.kt
β βββ KeywordFallbackAssistant.kt
βββ data/
β βββ DocBundleLoader.kt β interface + DefaultDocBundleLoader
β βββ KeywordSearchEngine.kt β TF-IDF keyword search
βββ di/
β βββ FeatureDocsModule.kt β Koin module
βββ model/
β βββ DocModels.kt β DocSection, DocPage, DocBundle, DocSearchResult, ...
βββ navigation/
β βββ DocsNavigation.kt β docsEntries(), ChirpyUiState, rememberChirpyState()
βββ translation/
β βββ DocTranslationService.kt β ML Kit (Google) or no-op (fdroid/desktop/iOS)
β βββ DocTranslationCache.kt
β βββ MarkdownTranslationSegmenter.kt
β βββ NoOpDocTranslator.kt
βββ ui/
βββ DocsBrowserScreen.kt β list pane
βββ DocsPageRouteScreen.kt β detail pane
βββ DocsSearchBar.kt
βββ ChirpyAssistantSheet.kt β AI assistant bottom sheet
βββ ChirpyFab.kt β floating action button that opens Chirpy
βββ ComposeResourceImageTransformer.kt
βββ DocPageIconResolver.kt
βββ DocsPreviews.kt
Key Types
T383838DocSection (sealed interface)
T282828
Tff7b72sealed Tff7b72interface T56d364DocSection Tb4b4b4{
Tff7b72data Tff7b72object T56d364UserGuide Tb4b4b4: Te6edf3DocSection
Tff7b72data Tff7b72object T56d364DeveloperGuide Tb4b4b4: Te6edf3DocSection
Tb4b4b4}
T383838DocPage
T282828
Tff7b72data Tff7b72class T56d364DocPageTb4b4b4(
Tff7b72val Te6edf3idTb4b4b4: Tffa657StringTb4b4b4,
Tff7b72val Te6edf3titleTb4b4b4: Tffa657StringTb4b4b4,
Tff7b72val Te6edf3sectionTb4b4b4: Te6edf3DocSectionTb4b4b4,
Tff7b72val Te6edf3navOrderTb4b4b4: Tffa657IntTb4b4b4,
Tff7b72val Te6edf3resourcePathTb4b4b4: Tffa657StringTb4b4b4,
Tff7b72val Te6edf3keywordsTb4b4b4: Te6edf3ListTff7b72<Tffa657StringTff7b72>Tb4b4b4,
Tff7b72val Te6edf3charCountTb4b4b4: Tffa657IntTb4b4b4,
Tb4b4b4)
T383838AIDocAssistant (interface)
T282828
Tff7b72interface T56d364AIDocAssistant Tb4b4b4{
Tff7b72suspend Tff7b72fun Td2a8ffisSupportedTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657Boolean
Tff7b72val Te6edf3modelStatusTb4b4b4: Te6edf3StateFlowTff7b72<Te6edf3ModelReadinessTff7b72>
Tff7b72suspend Tff7b72fun Td2a8ffanswerTb4b4b4(Te6edf3questionTb4b4b4: Tffa657StringTb4b4b4, Te6edf3currentPageIdTb4b4b4: Tffa657String? Tff7b72= Tff7b72nullTb4b4b4)Tb4b4b4: Te6edf3AIDocAssistantResult
Tff7b72fun Td2a8ffanswerStreamTb4b4b4(Te6edf3questionTb4b4b4: Tffa657StringTb4b4b4, Te6edf3currentPageIdTb4b4b4: Tffa657String? Tff7b72= Tff7b72nullTb4b4b4)Tb4b4b4: Te6edf3FlowTff7b72<Te6edf3AIDocAssistantResultTff7b72>
Tff7b72fun Td2a8ffresetSessionTb4b4b4(Tb4b4b4)
Tb4b4b4}
T383838AIDocAssistantResult is a sealed interface: T383838Partial, T383838Success, T383838Fallback, T383838Error.
Platform bindings:
β’ Google flavor: Gemini Nano via on-device ML
β’ F-Droid / Desktop / iOS: T383838KeywordFallbackAssistant (keyword search + summarisation, no network)
T383838ChirpyMessage
T282828
Tf0883e@Serializable
Tff7b72data Tff7b72class T56d364ChirpyMessageTb4b4b4(
Tff7b72val Te6edf3idTb4b4b4: Tffa657StringTb4b4b4,
Tff7b72val Te6edf3roleTb4b4b4: Te6edf3ChirpyRoleTb4b4b4, T8b949e// USER | ASSISTANT | SYSTEM
Tff7b72val Te6edf3textTb4b4b4: Tffa657StringTb4b4b4,
Tff7b72val Te6edf3sourcesTb4b4b4: Te6edf3ListTff7b72<Te6edf3SourceRefTff7b72>Tb4b4b4,
Tb4b4b4)
Gradle Tasks
Two custom tasks keep bundled docs in sync:
ββββββββββββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Task β Description β
ββββββββββββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β T383838syncDocsToComposeResources β Copies T383838docs/en/user/**/*.md and T383838docs/en/developer/**/*.mβ¦ β
β T383838syncTranslatedDocsToComposeResources β Copies Crowdin-translated locales from T383838docs/{locale}/useβ¦ β
ββββββββββββββββββββββββββββββββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
These tasks run automatically β no manual invocation is required during normal development.
Navigation
Routes (registered under the Settings nav graph):
βββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββ
β Route β Description β
βββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββ€
β T383838SettingsRoute.HelpDocs β Doc browser list pane β
β T383838SettingsRoute.HelpDocPage β Individual doc page detail pane β
βββββββββββββββββββββββββββββ΄ββββββββββββββββββββββββββββββββββ
The T383838docsEntries() extension uses Material3 adaptive T383838ListDetailSceneStrategy to automatically provide a split-pane layout on large screens.
Dependency Graph
Key Dependencies
T282828
feature:docs
βββ core:common, core:navigation, core:resources, core:ui, core:di
βββ coil (image loading in Markdown)
βββ markdown-renderer-m3 (Compose Markdown rendering)
βββ compose.material3.adaptive, compose.material3.adaptive.navigation3
βββ kotlinx.collections.immutable
<!--region graph-->
T282828
Te6edf3graph Te6edf3TB
:Te6edf3featureTb4b4b4:Te6edf3docsTff7b72[Te6edf3docsTff7b72]Tff7b72:::Te6edf3kmpTff7b72-Te6edf3feature
:Te6edf3featureTb4b4b4:Te6edf3docs Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Te6edf3common
:Te6edf3featureTb4b4b4:Te6edf3docs Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Te6edf3navigation
:Te6edf3featureTb4b4b4:Te6edf3docs Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Te6edf3resources
:Te6edf3featureTb4b4b4:Te6edf3docs Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Te6edf3ui
:Te6edf3featureTb4b4b4:Te6edf3docs Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Te6edf3di
:Te6edf3featureTb4b4b4:Te6edf3docs Tff7b72-Tb4b4b4.Tff7b72-Tff7b72> :Te6edf3coreTb4b4b4:Te6edf3testing
Te6edf3classDef Te6edf3androidTff7b72-Te6edf3application Te6edf3fillTb4b4b4:Te6edf3#CAFFBFTb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Te6edf3androidTff7b72-Te6edf3applicationTff7b72-Te6edf3compose Te6edf3fillTb4b4b4:Te6edf3#CAFFBFTb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Te6edf3composeTff7b72-Te6edf3desktopTff7b72-Te6edf3application Te6edf3fillTb4b4b4:Te6edf3#CAFFBFTb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Te6edf3androidTff7b72-Te6edf3feature Te6edf3fillTb4b4b4:Te6edf3#FFD6A5Tb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Te6edf3androidTff7b72-Te6edf3library Te6edf3fillTb4b4b4:Te6edf3#9BF6FFTb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Te6edf3androidTff7b72-Te6edf3libraryTff7b72-Te6edf3compose Te6edf3fillTb4b4b4:Te6edf3#9BF6FFTb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Te6edf3androidTff7b72-Te6edf3test Te6edf3fillTb4b4b4:Te6edf3#A0C4FFTb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Te6edf3jvmTff7b72-Te6edf3library Te6edf3fillTb4b4b4:Te6edf3#BDB2FFTb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Te6edf3kmpTff7b72-Te6edf3feature Te6edf3fillTb4b4b4:Te6edf3#FFD6A5Tb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Te6edf3kmpTff7b72-Te6edf3libraryTff7b72-Te6edf3compose Te6edf3fillTb4b4b4:Te6edf3#FFC1CCTb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Te6edf3kmpTff7b72-Te6edf3library Te6edf3fillTb4b4b4:Te6edf3#FFC1CCTb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
Te6edf3classDef Tff7b72unknown Te6edf3fillTb4b4b4:Te6edf3#FFADADTb4b4b4,Te6edf3strokeTb4b4b4:Te6edf3#000Tb4b4b4,Te6edf3strokeTff7b72-Te6edf3widthTb4b4b4:T79c0ff2Te6edf3pxTb4b4b4,Te6edf3colorTb4b4b4:Te6edf3#000Tb4b4b4;
<!--endregion-->
Served by rngit 1.5.0 - Generated in 0.07s